package com.wish.datastructure;

/**
 * Created by suliucheng on 2021/4/6 18:58
 * Directions:实现双向链表的 增删改查
 */
public class DoubleLinkedList {
    public static void main(String[] args) {
        DoubleLinkedListDemo listDemo = new DoubleLinkedListDemo();
        listDemo.add(new DbNode(1, "中国"));
        listDemo.add(new DbNode(2, "美国"));
        listDemo.add(new DbNode(3, "日本"));
        listDemo.add(new DbNode(4, "德国"));
        System.out.println("顺序打印链表的结果：");
        listDemo.list("order");
        System.out.println("逆序打印链表的结果：");
        listDemo.list("reverse");
        System.out.println("将“德国”改成“英国”：");
        listDemo.update(new DbNode(4, "英国"));
        listDemo.list("order");
        System.out.println("删除“美国”：");
        listDemo.delete(2);
        listDemo.list("order");
    }
}

/**
 * 双向链表类：管理节点类
 */
class DoubleLinkedListDemo {
    static DbNode head = new DbNode(0, "theFirst");
    static DbNode end = new DbNode(-1, "theEnd");

    static {
        head.next = end;
        end.pre = head;
    }

    /**
     * 根据编号删除节点
     * @param number 节点编号
     */
    public void delete(Integer number) {
        DbNode temp = head;
        while (true){
            if(temp==end){
                break;
            }
            temp = temp.next;
            if(temp.number ==number){
                temp.pre.next = temp.next;
                temp.next.pre = temp.pre;
                return;
            }
        }
        throw new RuntimeException("参数异常：不存在此编号的节点("+number+")");
    }


    /**
     * s顺序查找
     *
     * @param node 被修改的节点的编号
     */
    public void update(DbNode node) {
        DbNode temp = head;
        while (true) {
            if (temp == end) {
                break;
            } else if (temp.number == node.number) {
                temp.data = node.data;
                return;
            }
            temp = temp.next;
        }
        throw new RuntimeException("参数异常：不存在此编号的节点("+node.number+")");
    }

    /**
     * 给链表的最后添加一个新的节点
     *
     * @param node 新的节点对象
     */
    public void add(DbNode node) {
        //从头部开始移动的临时指针
        DbNode temp = head;
        while (true) {
            if (temp.next == end) {
                break;
            }
            temp = temp.next;
        }
        temp.next = node;
        node.pre = temp;

        node.next = end;
        end.pre = node;
    }

    /**
     * way: {
     * order:顺序,
     * reverse:逆序
     * }
     *
     * @param way 以某一种形式来遍历链表
     */
    public void list(String way) {
        switch (way) {
            case "order":
                listOrder();
                break;
            case "reverse":
                listReverse();
                break;
            default:
                throw new RuntimeException("参数异常：" + way);
        }

    }

    /**
     * 顺序遍历双向链表
     * 通过 next
     */
    private void listOrder() {
        if (head.next == null) {
            System.out.println("当前链表为空");
        }
        DbNode temp = head;
        while (true) {
            if (temp.next == end) {
                break;
            }
            //移动到下一个节点
            temp = temp.next;
            System.out.println(temp);
        }
    }

    /**
     * 逆序遍历双向链表
     */
    private void listReverse() {
        if (end.pre == null) {
            System.out.println("当前链表为空");
        }
        DbNode temp = end;
        while (true) {
            if (temp.pre == head) {
                break;
            }
            //移动到下一个节点
            temp = temp.pre;
            System.out.println(temp);
        }
    }
}


/**
 * 双向链表的节点包含编号，数据，前一个节点的地址，后一个节点的地址
 * 区别单向链表只有一个指向后一个节点的地址
 */
class DbNode {
    int number;
    String data;
    DbNode pre;
    DbNode next;

    public void setPre(DbNode pre) {
        this.pre = pre;
    }

    public void setNext(DbNode next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "DbNode{" +
                "number=" + number +
                ", data='" + data + '\'' +
                '}';
    }

    public DbNode(int number, String data) {
        this.number = number;
        this.data = data;
    }
}